<?php

namespace App\Model;

use Hyperf\Collection\Collection;
use Hyperf\Context\ApplicationContext;
use Hyperf\Database\Model\Relations\BelongsTo;
use Hyperf\Database\Model\Relations\BelongsToMany;
use Hyperf\Database\Model\Relations\HasMany;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Arr;
use Hyperf\Redis\Redis;
use Carbon\Carbon;
use PHPUnit\Util\Test;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use RedisException;


class Device extends Model
{
    const SIGNAL_TIME_OUT = 'signal_time_out';

    public bool $timestamps = true;
    protected ?string $table = 'devices';

    private const GEO_KEY = 'devices:geo';

    const ONLINE = 1;// 设备在线
    const NOT_ONLINE = 0;// 设备不在线

    protected array $guarded = [
        'id'
        // 列出所有不想被批量赋值的字段（黑名单）
        // 其他未列出的字段将允许批量赋值
    ];

    protected array $casts = [
        'last_online_at' => 'datetime',
        'active_at' => 'datetime',
        'expires_at' => 'datetime',
        'created_at'=>'datetime',
        'params_read_at' => 'datetime',
    ];

    const CHANNEL_MAX = 10;
//    const JOIN_DEPOSIT_FEE = 200;

    const RENEW_FEE = 25.00;


    //增加一次故障记录
    public function incrementOnceFault($reason)
    {
        $key = 'device_fault_' . $this->id;
        if(redis()->exists($key)){
            $times = redis()->get($key);
        }else{
             redis()->setex($key,60*10,0);
             $times = 0;
        }
        redis()->incr($key);
        try{
            if($times >= 3) {
                $deviceFaultLog = new DeviceFaultLog();
                $deviceFaultLog->device_id = $this->id;
                $deviceFaultLog->remark = $reason;
                $deviceFaultLog->save();
                $this->is_fault = true;
                $this->save();
                //清除故障记录
                redis()->del($key);
            }
        }catch (\Exception $e){

        }
    }


    public function station() :BelongsTo{
        return $this->belongsTo(Station::class,'station_id','id');
    }

    public function charge() :BelongsTo{
        return $this->belongsTo(ChargeOption::class,'charge_id','id');
    }


    public function orders()
    {
        return $this->hasMany(Order::class,'device_id','id');
    }

    public function port():HasMany{
        return $this->hasMany(DevicePort::class,'device_id','id');
    }


    public static function getCharge($chargeId){
        if($chargeId <= 0){
            $charge = ChargeOption::where('distributor_id',0)
                ->where('is_del',1)
                ->with('time_children','power_children','service_children')
                ->first();
        }else{
            $charge = ChargeOption::where('id',$chargeId)
                ->with('time_children','power_children','service_children')
                ->first();
        }
        return $charge;
    }

    public function statusParse($status):array{
        $arr['over_load'] = ($status & 0x01);       // bit0: 过载位
        $arr['over_current'] = ($status & 0x02) >> 1; // bit1: 过流位
        $arr['over_temp'] = ($status & 0x04) >> 2;    // bit2: 过温
        $arr['no_load'] = ($status & 0x08) >> 3;       // bit3: 空载位
        $arr['charge_status'] = ($status & 0x30) >> 4;   // bit4-5: 充电位
        $arr['is_fault'] = ($status & 0x40) >> 6;   // bit6: 计量电路故障
        $arr['inline'] = ($status & 0x80) >> 7;      // bit7: 在线状态
        return $arr;
    }







    /**
     * 设置设备在线
     * @param $mac
     * @param $fd
     * @return bool
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws RedisException
     */
    public static function setDeviceOnline($mac,$fd):bool
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        $result = $redis->hSet('device_online', (string)$mac, (string)$fd);
        return is_int($result);
    }

    /**
     * 设置设备不在线
     * @param $mac
     * @return bool
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws RedisException
     */
    public static function setDeviceNotOnline($mac): bool
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        $result = $redis->hDel('device_online', (string)$mac);
        return is_int($result);
    }

    /**
     * 通过设备mac获取在线设备的FD客户端ID
     * @param $mac
     * @return string
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws RedisException
     */
    public static function getFdByMac($mac): string
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        return (string)$redis->hGet('device_online', (string)$mac);
    }
}
